home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / storage / smgr / jbaccess.c next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  16.6 KB  |  714 lines

  1. /*
  2.  *  jbaccess.c -- Access interface code for the Sony WORM jukebox.
  3.  *
  4.  *    This file is only used if you're at Berkeley and you have
  5.  *    SONY_JUKEBOX defined.  This file was swiped from Andy McFadden's
  6.  *    jukebox management library and adapted to Postgres.
  7.  */
  8.  
  9. #include "tmp/c.h"
  10. #include "tmp/postgres.h"
  11.  
  12. #ifdef SONY_JUKEBOX
  13.  
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <sys/types.h>
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <netdb.h>
  20. #include <errno.h>
  21.  
  22. #include "storage/jbstruct.h"
  23. #include "storage/jbcomm.h"
  24. #include "storage/jblib.h"
  25.  
  26. RcsId("$Header: /private/postgres/src/storage/smgr/RCS/jbaccess.c,v 1.4 1991/11/04 10:53:55 hong Exp $");
  27.  
  28. /* debugging aid */
  29. /* # define DBUG(x) if (jb_debug) printf x */
  30. # define DBUG(x)
  31.  
  32. /*
  33.  * One of these for every connection to the server.
  34.  * For now, only one of these is needed.
  35.  */
  36.  
  37. typedef struct {
  38.     int sock;            /* fd of server socket connection */
  39.     int error;            /* last error result for this connection */
  40. } SERVER;
  41.  
  42. /*
  43.  * globals
  44.  *
  45.  * These can be set from the client program if desired.
  46.  */
  47.  
  48. int jb_debug = 0;            /* 0=no, 1=debug messages */
  49. int jb_server_port = JB_SERVER_PORT;    /* server port# */
  50. char *jb_server_mach = JB_SERVER_MACH;    /* server machine name */
  51.  
  52. /*
  53.  * private variables
  54.  */
  55.  
  56. static SERVER server;        /* connection to server */
  57.  
  58. /*
  59.  * ----------------------------------------------------------------------
  60.  *    subroutines
  61.  * ----------------------------------------------------------------------
  62.  */
  63.  
  64. /*
  65.  * Send a message to the server (blocking).
  66.  *
  67.  * "buf" should have JB_DATA_START bytes of free space at the front
  68.  * (i.e., the buffer copying should be performed by the caller).  This
  69.  * routine sticks the generic header data into the buffer, and then
  70.  * sends it to the server.
  71.  */
  72. static int
  73. send_to_server(nbytes, type, unused, buf)
  74. int nbytes;
  75. short type, unused;
  76. char *buf;
  77. {
  78.     int count, cc;
  79.  
  80.     DBUG((">+> Sending %d bytes\n", nbytes));
  81.  
  82.     *((int   *) (buf+0)) = htonl(nbytes);
  83.     *((short *) (buf+4)) = htons(type);
  84.     *((short *) (buf+6)) = htons(unused);
  85.  
  86.     for (count = 0; count < nbytes; count += cc)
  87.     if ((cc = write(server.sock, buf+count, nbytes-count)) <= 0) {
  88.         if (jb_debug) perror(">+> unable to write to server");
  89.         server.error = JB_ESERVER;
  90.         return (-1);
  91.     }
  92.  
  93.     return (0);
  94. }
  95.  
  96.  
  97. /*
  98.  * Force a non-blocking read of nbytes bytes on a socket.
  99.  *
  100.  * Returns 0 on success, -1 on error.
  101.  */
  102. static int
  103. nb_read(csock, buf, nbytes)
  104. int csock, nbytes;
  105. char *buf;
  106. {
  107.     int count, cc;
  108.  
  109.     for (count = 0; count < nbytes; count += cc)
  110.     if ((cc = read(csock, buf+count, nbytes-count)) <= 0) {
  111.         if (!cc) {
  112.         return (-1);    /* EOF - disconnected? */
  113.         } else {
  114.         perror(">+> Read error");
  115.         return (-1);
  116.         }
  117.     }
  118.  
  119.     return (0);
  120. }
  121.  
  122.  
  123. /*
  124.  * receive a message from the server (blocking)
  125.  *
  126.  * This interprets the first word of the "data" area as the return code,
  127.  * and acts accordingly (sets server.error and returns -1 if a nonzero
  128.  * error code is returned).  "exp_type" should be the type of REPLY
  129.  * expected; mismatched types cause a "JB_EINTERNAL" error.
  130.  *
  131.  * Note that "buf" must be large enough to hold the incoming message.
  132.  * This is somewhat dangerous during JB_READ_REPLYs.
  133.  */
  134. static int
  135. recv_from_server(type_p, size_p, buf, exp_type)
  136. short *type_p;
  137. int *size_p, exp_type;
  138. char *buf;
  139. {
  140.     int size, error;
  141.     short type;
  142.  
  143.     /* wait on socket until JB_DATA_START bytes are read (header only) */
  144.     if (nb_read(server.sock, buf, JB_DATA_START) < 0) {
  145.     DBUG((">+> first part of read failed\n"));
  146.     server.error = JB_ESERVER;
  147.     return (-1);
  148.     }
  149.  
  150.     size = ntohl(*((int   *) (buf +0)));
  151.     type = ntohs(*((short *) (buf +4)));
  152.  
  153.     if (size > JB_DATA_START) {
  154.     if (nb_read(server.sock, buf+JB_DATA_START, size-JB_DATA_START) < 0) {
  155.         DBUG((">+> second part of read failed\n"));
  156.         server.error = JB_ESERVER;
  157.         return (-1);
  158.     }
  159.     }
  160.  
  161.     *size_p = size;
  162.     *type_p = type;
  163.  
  164.     /* check return type */
  165.     if (type != exp_type) {
  166.     server.error = JB_EINTERNAL;
  167.     return (-1);
  168.     }
  169.  
  170.     /* check return status (+00 in data area) */
  171.     error = ntohl(*((int *) (buf + JB_DATA_START +0)));
  172.  
  173.     if (error) {
  174.     DBUG((">+> Got an error response, code = %d\n", error));
  175.     server.error = error;
  176.     return (-1);
  177.     }
  178.  
  179.     DBUG((">+> Received %d bytes\n", size));
  180.  
  181.     return (0);
  182. }
  183.  
  184.  
  185. /*
  186.  * ----------------------------------------------------------------------
  187.  *    main library routines
  188.  * ----------------------------------------------------------------------
  189.  */
  190.  
  191. /*
  192.  * Implementation note:
  193.  *   The server sends back a 4-byte magic cookie (which is actually a
  194.  *   pointer to a JBPLATTER structure on the server machine) for jb_open()
  195.  *   calls, and expects it to be passed on subsequent calls.  However,
  196.  *   the client code is not allowed to interpret this value in any way,
  197.  *   so future implementations of this library may instead pass a pointer
  198.  *   to a local structure holding stuff like a file descriptor (useful if
  199.  *   we get multiple jukeboxes).
  200.  */
  201.  
  202. /*
  203.  * jb_init
  204.  */
  205. int
  206. jb_init(version)
  207. char *version;
  208. {
  209.     char init_buf[JB_DATA_START + 8];
  210.     int length, rval, size;
  211.     short type;
  212.     struct sockaddr_in server_addr;
  213.     struct hostent *hp;
  214.  
  215.     DBUG((">+> Initializing client v%s\n", version));
  216.     server.sock = -1;
  217.     server.error = JB_ENOSERVER;    /* only possible error for now */
  218.  
  219.     /* create the socket */
  220.     if ((server.sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  221.     if (jb_debug) perror(">+> unable to open stream socket");
  222.     return (-1);
  223.     }
  224.  
  225.     /* locate host */
  226.     server_addr.sin_family = AF_INET;
  227.     if ((hp = gethostbyname(jb_server_mach)) == 0) {
  228.     return (-1);
  229.     }
  230.     bcopy(hp->h_addr, &server_addr.sin_addr, hp->h_length);
  231.     server_addr.sin_port = htons((short) jb_server_port);
  232.  
  233.     if ((connect(server.sock, (struct sockaddr *) &server_addr,
  234.                         sizeof(server_addr))) < 0) {
  235.     perror(">>> connecting stream socket");
  236.     return (-1);
  237.     }
  238.  
  239.     /* send init request to server */
  240.     if (send_to_server(8, JB_INIT_REQ, 0, init_buf) < 0) {
  241.     return (-1);
  242.     }
  243.  
  244.     /* wait for response */
  245.     if (recv_from_server(&type, &size, init_buf, JB_INIT_REPLY) < 0) {
  246.     return (-1);
  247.     }
  248.  
  249.     server.error = 0;
  250.  
  251.     return (0);
  252. }
  253.  
  254.  
  255. JBPLATTER *
  256. jb_open(platter_id, format, flags)
  257. char *platter_id;
  258. char *format;
  259. int flags;
  260. {
  261.     JBPLATTER *jbp;
  262.     long hold;
  263.     char req[JB_DATA_START + 4 + JB_MAX_NAME+1 + JB_MAX_FORMAT+1];
  264.     char reply[JB_DATA_START + 8];
  265.     char *r = &reply[0]; /* necessary for casts to work on Sparcstation */
  266.     int size, len;
  267.     short type;
  268.  
  269.     server.error = 0;
  270.     len = JB_DATA_START + 4 + strlen(platter_id)+1 + strlen(format)+1;
  271.     *((long *) (req+JB_DATA_START)) = htonl(flags);
  272.     strcpy(req+4+JB_DATA_START, platter_id);
  273.     strcpy(req+4+JB_DATA_START+strlen(platter_id)+1, format);
  274.  
  275.     if (send_to_server(len, JB_OPEN_REQ, 0, req) < 0)
  276.     return (NULL);
  277.     if (recv_from_server(&type, &size, reply, JB_OPEN_REPLY) < 0)
  278.     return (NULL);
  279.  
  280.     /* what a mess */
  281.     hold = *((long *)(r+JB_DATA_START+4));
  282.     jbp = (JBPLATTER *) ntohl(hold);
  283.  
  284.     return (jbp);
  285. }
  286.  
  287.  
  288. int
  289. jb_read(platter, buf, blockno, nblocks)
  290. JBPLATTER *platter;
  291. char *buf;
  292. long blockno, nblocks;
  293. {
  294.     char req[JB_DATA_START + 12], *reply;
  295.     int size, len;
  296.     short type;
  297.  
  298.     /* skip over label blocks */
  299.     if (blockno >= 0)
  300.     blockno += JB_MAX_LABELS;
  301.  
  302.     server.error = 0;
  303.     if (blockno < 0 || nblocks < 0) {
  304.     server.error = JB_ERANGE;
  305.     return (-1);
  306.     }
  307.  
  308.     *((long *) (req+JB_DATA_START+0)) = htonl((long) platter);
  309.     *((long *) (req+JB_DATA_START+4)) = htonl(blockno);
  310.     *((long *) (req+JB_DATA_START+8)) = htonl(nblocks);
  311.  
  312.     if (send_to_server(JB_DATA_START+12, JB_READ_REQ, 0, req) < 0)
  313.     return (-1);
  314.     len = nblocks * JB_BLOCK_SIZE;
  315.     reply = (char *) malloc(JB_DATA_START+4 +len);
  316.     if (recv_from_server(&type, &size, reply, JB_READ_REPLY) < 0) {
  317.     free (reply);
  318.     return (-1);
  319.     }
  320.  
  321.     if (size != len + JB_DATA_START+4) {
  322.     free(reply);
  323.     return (-1);
  324.     }
  325.  
  326.     bcopy(reply+JB_DATA_START+4, buf, len);
  327.     free(reply);
  328.  
  329.     return (0);
  330. }
  331.  
  332.  
  333. int
  334. jb_write(platter, buf, blockno, nblocks)
  335. JBPLATTER *platter;
  336. char *buf;
  337. long blockno, nblocks;
  338. {
  339.     char *req, reply[JB_DATA_START+4];
  340.     int size, len, data_len;
  341.     short type;
  342.  
  343.     /* skip over label blocks */
  344.     if (blockno >= 0)
  345.     blockno += JB_MAX_LABELS;
  346.  
  347.     server.error = 0;
  348.     if (blockno < 0 || nblocks < 0) {
  349.     server.error = JB_ERANGE;
  350.     return (-1);
  351.     }
  352.  
  353.     data_len = nblocks * JB_BLOCK_SIZE;
  354.     len = data_len + JB_DATA_START +12;
  355.     if ((req = (char *) malloc(len)) == NULL) {
  356.     server.error = JB_EINTERNAL;
  357.     return (-1);
  358.     }
  359.     *((long *) (req+JB_DATA_START+0)) = htonl((long) platter);
  360.     *((long *) (req+JB_DATA_START+4)) = htonl(blockno);
  361.     *((long *) (req+JB_DATA_START+8)) = htonl(nblocks);
  362.     bcopy(buf, req+JB_DATA_START+12, data_len);
  363.  
  364.     if (send_to_server(len, JB_WRITE_REQ, 0, req) < 0) {
  365.     free(req);
  366.     return (-1);
  367.     }
  368.     free(req);
  369.     if (recv_from_server(&type, &size, reply, JB_WRITE_REPLY) < 0)
  370.     return (-1);
  371.  
  372.     return (0);
  373. }
  374.  
  375.  
  376. int
  377. jb_close(platter)
  378. JBPLATTER *platter;
  379. {
  380.     char req[JB_DATA_START + 4];
  381.     char reply[JB_DATA_START + 4];
  382.     short type;
  383.     int size;
  384.  
  385.     server.error = 0;
  386.     *((long *) (req+JB_DATA_START)) = htonl((long) platter);
  387.  
  388.     if (send_to_server(JB_DATA_START+4, JB_CLOSE_REQ, 0, req) < 0)
  389.     return (-1);
  390.     if (recv_from_server(&type, &size, reply, JB_CLOSE_REPLY) < 0)
  391.     return (-1);
  392.  
  393.     return (0);
  394. }
  395.  
  396.  
  397. int
  398. jb_istat(platter_id, jbsp)
  399. char *platter_id;
  400. JBSTATUS *jbsp;
  401. {
  402.     char req[JB_DATA_START + JB_MAX_NAME+1];
  403.     char reply[JB_DATA_START + 4 + JBSTATUS_SIZE+sizeof(JBLABEL)];
  404.     short type;
  405.     int size, data_len;
  406.  
  407.     server.error = 0;
  408.     data_len = JB_DATA_START + strlen(platter_id)+1;
  409.     strcpy(req + JB_DATA_START, platter_id);
  410.  
  411.     if (send_to_server(data_len, JB_ISTAT_REQ, 0, req) < 0) {
  412.     free(req);
  413.     return (-1);
  414.     }
  415.     free(req);
  416.     if (recv_from_server(&type, &size, reply, JB_ISTAT_REPLY) < 0)
  417.     return (-1);
  418.  
  419.     jbsp->location = ntohl(*((long *) (reply+JB_DATA_START+ 4)));
  420.     jbsp->access   = ntohl(*((long *) (reply+JB_DATA_START+ 8)));
  421.     jbsp->locked   = ntohl(*((long *) (reply+JB_DATA_START+12)));
  422.     jbsp->offset   = ntohl(*((long *) (reply+JB_DATA_START+16)));
  423.     bcopy(reply+JB_DATA_START+4+JBSTATUS_SIZE, &(jbsp->label), sizeof(JBLABEL));
  424.  
  425.     return (0);
  426. }
  427.  
  428.  
  429. int
  430. jb_fstat(platter, jbsp)
  431. JBPLATTER *platter;
  432. JBSTATUS *jbsp;
  433. {
  434.     char req[JB_DATA_START + 4];
  435.     char reply[JB_DATA_START + 4 + JBSTATUS_SIZE+sizeof(JBLABEL)];
  436.     short type;
  437.     int size;
  438.  
  439.     server.error = 0;
  440.     *((long *) (req+JB_DATA_START)) = htonl((long) platter);
  441.  
  442.     if (send_to_server(JB_DATA_START+4, JB_FSTAT_REQ, 0, req) < 0)
  443.     return (-1);
  444.     if (recv_from_server(&type, &size, reply, JB_FSTAT_REPLY) < 0)
  445.     return (-1);
  446.  
  447.     jbsp->location = ntohl(*((long *) (reply+JB_DATA_START+ 4)));
  448.     jbsp->access   = ntohl(*((long *) (reply+JB_DATA_START+ 8)));
  449.     jbsp->locked   = ntohl(*((long *) (reply+JB_DATA_START+12)));
  450.     jbsp->offset   = ntohl(*((long *) (reply+JB_DATA_START+16)));
  451.     bcopy(reply+JB_DATA_START+4+JBSTATUS_SIZE, &(jbsp->label), sizeof(JBLABEL));
  452.  
  453.     return (0);
  454. }
  455.  
  456.  
  457. long
  458. jb_scanb(platter, start_block, search_max)
  459. JBPLATTER *platter;
  460. long start_block, search_max;
  461. {
  462.     char req[JB_DATA_START +12];
  463.     char *reply = &req[0];        /* only need JDS+8 for reply */
  464.     short type;
  465.     int size;
  466.     long result;
  467.  
  468.     /* skip over label blocks */
  469.     if (start_block >= 0)
  470.     start_block += JB_MAX_LABELS;
  471.  
  472.     server.error = 0;
  473.     *((long *) (req+JB_DATA_START+0)) = htonl((long) platter);
  474.     *((long *) (req+JB_DATA_START+4)) = htonl(start_block);
  475.     *((long *) (req+JB_DATA_START+8)) = htonl(search_max);
  476.  
  477.     if (send_to_server(JB_DATA_START+12, JB_SCANB_REQ, 0, req) < 0)
  478.     return (-1);
  479.     if (recv_from_server(&type, &size, reply, JB_SCANB_REPLY) < 0)
  480.     return (-1);
  481.  
  482.     result = ntohl(*((long *) (reply+JB_DATA_START+ 4)));
  483.  
  484.     if (result < 0)
  485.     return (-2L);
  486.  
  487.     /* restore the user's notion of block zero */
  488.     result -= JB_MAX_LABELS;
  489.  
  490.     return (result);
  491. }
  492.  
  493.  
  494. long
  495. jb_scanw(platter, start_block, search_max)
  496. JBPLATTER *platter;
  497. long start_block, search_max;
  498. {
  499.     char req[JB_DATA_START +12];
  500.     char *reply = &req[0];        /* only need JDS+8 for reply */
  501.     short type;
  502.     int size;
  503.     long result;
  504.  
  505.     /* skip over label blocks */
  506.     if (start_block >= 0)
  507.     start_block += JB_MAX_LABELS;
  508.  
  509.     server.error = 0;
  510.     *((long *) (req+JB_DATA_START+0)) = htonl((long) platter);
  511.     *((long *) (req+JB_DATA_START+4)) = htonl(start_block);
  512.     *((long *) (req+JB_DATA_START+8)) = htonl(search_max);
  513.  
  514.     if (send_to_server(JB_DATA_START+12, JB_SCANW_REQ, 0, req) < 0)
  515.     return (-1);
  516.     if (recv_from_server(&type, &size, reply, JB_SCANW_REPLY) < 0)
  517.     return (-1);
  518.  
  519.     result = ntohl(*((long *) (reply+JB_DATA_START+ 4)));
  520.  
  521.     if (result < 0)
  522.     return (-2L);
  523.  
  524.     /* restore the user's notion of block zero */
  525.     result -= JB_MAX_LABELS;
  526.  
  527.     return (result);
  528. }
  529.  
  530.  
  531. int
  532. jb_eject(platter_id)
  533. char *platter_id;
  534. {
  535.     char req[JB_DATA_START + JB_MAX_NAME+1];
  536.     char reply[JB_DATA_START + 4];
  537.     short type;
  538.     int size, data_len;
  539.  
  540.     server.error = 0;
  541.     data_len = JB_DATA_START + strlen(platter_id)+1;
  542.     strcpy(req + JB_DATA_START, platter_id);
  543.  
  544.     if (send_to_server(data_len, JB_EJECT_REQ, 0, req) < 0) {
  545.     return (-1);
  546.     }
  547.     if (recv_from_server(&type, &size, reply, JB_EJECT_REPLY) < 0)
  548.     return (-1);
  549.  
  550.     return (0);
  551. }
  552.  
  553.  
  554. int
  555. jb_load()
  556. {
  557.     char reply[JB_DATA_START+4];
  558.     char *req = reply;        /* only JB_DATA_START needed */
  559.     short type;
  560.     int size;
  561.  
  562.     if (send_to_server(JB_DATA_START, JB_LOAD_REQ, 0, req) < 0)
  563.     return (-1);
  564.     if (recv_from_server(&type, &size, reply, JB_LOAD_REPLY) < 0)
  565.     return (-1);
  566.  
  567.     return (0);
  568. }
  569.  
  570.  
  571. int
  572. jb_label(platter_id, jblp)
  573. char *platter_id;
  574. JBLABEL *jblp;
  575. {
  576.     JBPLATTER *jbp;
  577.     char req[JB_DATA_START + JB_MAX_NAME+1 + sizeof(JBLABEL)];
  578.     char reply[JB_DATA_START + 4];
  579.     int size, len;
  580.     short type;
  581.     char *id;
  582.  
  583.     server.error = 0;
  584.     if (platter_id == NULL)        /* label brand new platter? */
  585.     id = "";
  586.     else
  587.     id = platter_id;
  588.  
  589.     len = JB_DATA_START + strlen(id)+1 + sizeof(JBLABEL);
  590.     strcpy(req+JB_DATA_START, id);
  591.     bcopy((char *) jblp, req+JB_DATA_START+strlen(id)+1, sizeof(JBLABEL));
  592.  
  593.     if (send_to_server(len, JB_LABEL_REQ, 0, req) < 0)
  594.     return (-1);
  595.     if (recv_from_server(&type, &size, reply, JB_LABEL_REPLY) < 0)
  596.     return (-1);
  597.  
  598.     return (0);
  599. }
  600.  
  601.  
  602. int
  603. jb_exit()
  604. {
  605.     char req[JB_DATA_START], reply[JB_DATA_START+4];
  606.     short type;
  607.     int size;
  608.  
  609.     server.error = 0;
  610.     if (send_to_server(JB_DATA_START, JB_EXIT_REQ, 0, req) < 0)
  611.     return (-1);
  612.     if (recv_from_server(&type, &size, reply, JB_EXIT_REPLY) < 0)
  613.     return (-1);
  614.  
  615.     return (0);
  616. }
  617.  
  618.  
  619. int
  620. jb_error()
  621. {
  622.     return (server.error);
  623. }
  624.  
  625.  
  626. char *
  627. jb_strerror(errnum)
  628. int errnum;
  629. {
  630.     static char ebuf[40];
  631.     static char *jb_errlist[JB_NERR] = {
  632.     /* 0*/ "no error",
  633.     /* 1*/ "unable to connect to server",
  634.     /* 2*/ "platter name not recognized",
  635.     /* 3*/ "platter is offline",
  636.     /* 4*/ "JBPLATTER pointer invalid",
  637.     /* 5*/ "format type mismatch",
  638.     /* 6*/ "invalid argument",
  639.     /* 7*/ "platter is open",
  640.     /* 8*/ "permission denied",
  641.     /* 9*/ "I/O error",
  642.     /*10*/ "error on server connection",
  643.     /*11*/ "tried to read blank sector",
  644.     /*12*/ "tried to write written sector",
  645.     /*13*/ "internal error",
  646.     /*14*/ "platter has no label or invalid label",
  647.     /*15*/ "can't change platter name",
  648.     /*16*/ "can't relabel platter in I/O port",
  649.     /*17*/ "invalid label",
  650.     /*18*/ "no more room for labels",
  651.     /*19*/ "server is rejecting debug commands",
  652.     /*20*/ "platter is open with nonzero offset"
  653.     };
  654.  
  655.     if ((unsigned int) errnum < JB_NERR)
  656.     return (jb_errlist[errnum]);
  657.  
  658.     sprintf(ebuf, "Unknown error: %d", errnum);
  659.     return (ebuf);
  660. }
  661.  
  662.  
  663. /*
  664.  * ----------------------------------------------------------------------
  665.  *    Debugging calls
  666.  * ----------------------------------------------------------------------
  667.  */
  668. int
  669. jb_offset(platter, offset)
  670. JBPLATTER *platter;
  671. long offset;
  672. {
  673.     char req[JB_DATA_START + 8];
  674.     char reply[JB_DATA_START + 4];
  675.     short type;
  676.     int size;
  677.  
  678.     server.error = 0;
  679.     *((long *) (req+JB_DATA_START+0)) = htonl((long) platter);
  680.     *((long *) (req+JB_DATA_START+4)) = htonl(offset);
  681.  
  682.     if (send_to_server(JB_DATA_START+8, JB_OFFSET_REQ, 0, req) < 0)
  683.     return (-1);
  684.     if (recv_from_server(&type, &size, reply, JB_OFFSET_REPLY) < 0)
  685.     return (-1);
  686.  
  687.     return (0);
  688. }
  689.  
  690. int
  691. jb_shelf_offset(shelf, side, offset)
  692. int shelf, side;
  693. long offset;
  694. {
  695.     char req[JB_DATA_START + 12];
  696.     char reply[JB_DATA_START + 4];
  697.     short type;
  698.     int size;
  699.  
  700.     server.error = 0;
  701.     *((long *) (req+JB_DATA_START+0)) = htonl(shelf);
  702.     *((long *) (req+JB_DATA_START+4)) = htonl(side);
  703.     *((long *) (req+JB_DATA_START+8)) = htonl(offset);
  704.  
  705.     if (send_to_server(JB_DATA_START+12, JB_SHELF_OFFSET_REQ, 0, req) < 0)
  706.     return (-1);
  707.     if (recv_from_server(&type, &size, reply, JB_SHELF_OFFSET_REPLY) < 0)
  708.     return (-1);
  709.  
  710.     return (0);
  711. }
  712.  
  713. #endif /* SONY_JUKEBOX */
  714.